package com.zzs.common.core.constant;

import com.zzs.common.core.enums.ProblemDifficulty;

import java.util.concurrent.TimeUnit;

/**
 * Redis 键常量类，封装了应用中使用的 Redis 键的定义和相关配置。
 * @author zzs
 * @date 2025/03/17
 */
public final class RedisKeyConsts {
    /**
     * 根据用户 ID 获取对应的 Redis 键，字符串存储。用来保存用户的登录状态, 只要这个键存在, 则认为用户已经登录。
     * 值：用户身份(role:int)，参考{@link com.zzs.common.core.enums.UserRole}
     * @param userId 用户 ID
     * @return 用户登录信息的 Redis 键
     */
    public static String getUserLoginKey(Long userId) {
        return "oj:user:login:" + userId;
    }

    /**
     * 用户登录状态的 Redis 键的有效期，单位为毫秒。
     * 此有效期与 JWT 的过期时间一致，确保一致性。
     */
    public static final long USER_LOGIN_EXPIRE_TIME = JwtConsts.TOKEN_EXPIRE_TIME;


    /**
     * 登录状态的 Redis 键有效期单位，单位为毫秒，与 JWT 有效期单位一致，最好不要修改。
     */
    public static final TimeUnit USER_LOGIN_TIME_UNIT = TimeUnit.MILLISECONDS;

    /**
     * 用户重置密码时对应的手机验证码, 有效期为5分钟
     */
    public static String getResetPasswordKey(Long userId) {
        return "oj:user:reset-password:" + userId;
    }

    public static final long RESET_PASSWORD_EXPIRE_TIME = 5L;

    public static final TimeUnit RESET_PASSWORD_TIME_UNIT = TimeUnit.MINUTES;

    public static String getProblemKey(long problemId) {
        return "oj:problem:detail:" + problemId;
    }

    /**
     * 使用zset存储所有已发布题目的id, 值和分数都是id
     */
    public static String getProblemIdZsetKey(Integer difficulty) {
        if (difficulty == null) {
            return "oj:problem:ids:total";
        } else if (difficulty == ProblemDifficulty.SIMPLE.getDifficulty()) {
            return "oj:problem:ids:simple";
        } else if (difficulty == ProblemDifficulty.MEDIUM.getDifficulty()) {
            return "oj:problem:ids:medium";
        } else if (difficulty == ProblemDifficulty.HARD.getDifficulty()) {
            return "oj:problem:ids:hard";
        }
        return "oj:problem:ids:total";
    }

    public static String getProblemCodeKey(long problemId, int language) {
        return "oj:problem:code:" + problemId + ":" + language;
    }

    public static String getTestCaseKey(long problemId) {
        return "oj:problem:case:" + problemId;
    }

    /**
     * 短信验证码的键
     */
    public static String getSmsCodeKey(String phone) {
        return "oj:sms:code:" + phone;
    }

    /**
     * 短信验证码有效期
     */
    public static final long SMS_CODE_EXPIRE_TIME = 5L;

    public static final TimeUnit SMS_CODE_TIME_UNIT = TimeUnit.MINUTES;

    /**
     * 当天所能获得的最大短信次数
     */
    public static String getSmsCountKey(String phone) {
        return "oj:sms:count:" + phone;
    }


    /**
     * 字符串结构.用户本次提交的代码是否处于判题状态, 只要这个键存在, 那就说明判题还未完成, 在这个期间用户无法再次提交代码
     * @param userId 用户id
     */
    public static String getJudgingKey(long userId) {
        return "oj:judging:" + userId;
    }

    public static long getJudgingExpireTime() {
        return 1L;
    }

    public static TimeUnit getJudgingTimeUnit() {
        return TimeUnit.MINUTES;
    }

    public static String getCodeSubmitKey(long codeSubmitId) {
        return "oj:code-submit:" + codeSubmitId;
    }

    public static long getCodeSubmitExpireTime() {
        return 5L;
    }

    public static TimeUnit getCodeSubmitTimeUnit() {
        return TimeUnit.MINUTES;
    }

//    字符串结构
    public static String getOldPhoneCodeKey(String phone) {
        return "oj:old-phone:code:" + phone;
    }

    public static long getOldPhoneCodeExpireTime() {
        return 5L;
    }

    public static String getNewPhoneCodeKey(String phone) {
        return "oj:new-phone:code:" + phone;
    }

    public static long getNewPhoneCodeExpireTime() {
        return 5L;
    }

    public static TimeUnit getNewPhoneCodeTimeUnit() {
        return TimeUnit.MINUTES;
    }

    public static TimeUnit getOldPhoneCodeTimeUnit() {
        return TimeUnit.MINUTES;
    }

    public static String getChangePhoneKey(long userId) {
        return "oj:change-phone:" + userId;
    }

    public static long getChangePhoneExpireTime() {
        return 5L;
    }

    public static TimeUnit getChangePhoneTimeUnit() {
        return TimeUnit.MINUTES;
    }

    public static String getUpdatePasswordCodeKey(String phone) {
        return "oj:update-password:" + phone;
    }

    public static long getUpdatePasswordCodeExpireTime() {
        return 5L;
    }

    public static TimeUnit getUpdatePasswordCodeTimeUnit() {
        return TimeUnit.MINUTES;
    }
}
